package com.yyge.handler;
/**
 *   绑定的处理器处理事件
 *   自定义Handle需要继承netty规定好的某个HandlerAdapter
 */

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.CharsetUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;


@Data
@Slf4j
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    //注入任务调度
    private Map<String,Object> data =  new HashMap<>();

    //连接用户 每一个连接只有一个
    private ChannelHandlerContext context = null;


    // 存储定时任务的引用，以便之后取消任务
    private ScheduledFuture<?> scheduledFuture;

    //!!!如果您有Utils或者是其他的Service 需要通过构造器注入的方式来进行注入 拿到对象
    // 该NettyServerHandler类 是每一个连接一个线程 不能在内部通过@Autowired 注入对象 否则为null
    public NettyServerHandler() {

    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);
    }

    /**
     * 当客户端连接到服务器完成就会出发该方法
     * @param ctx
     * @throws Exception 抛出异常
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx){
        System.out.println("连接啦");


//        String str="客户端连接通过建立完成";
//        ByteBuf opp = Unpooled.copiedBuffer(str.getBytes(CharsetUtil.UTF_8));
//        log.info("客户端连接通过建立完成:{}",opp);
//        ctx.writeAndFlush(opp);
    }

    /**
     * 读取客户端发送的数据
     * @param ctx 上下文对象,含通道channel,管代pipeline
     * @param msg 客户端发送的消息
     * @throws Exception 抛出异常
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        int i = System.identityHashCode(ctx);
        System.out.println(i);
        // 接收到客户端消息的处理逻辑
        System.out.println("[Client]: " + msg);
        if ("heartbeat".equals(msg)) {
            // 收到客户端的心跳请求，发送心跳应答消息
             String info="阿斯顿撒多";
             ByteBuf writeBuf = Unpooled.copiedBuffer(info.getBytes(CharsetUtil.UTF_8));
            ctx.channel().writeAndFlush(info);
        } else {
             String info="消息已收到";
             ByteBuf writeBuf = Unpooled.copiedBuffer(info.getBytes(CharsetUtil.UTF_8));
            // 收到其他消息，则按常规消息处理逻辑进行处理
            ctx.channel().writeAndFlush(writeBuf);
        }
    }

    /**
     * 数据读取完毕处理方法
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        int linkId = System.identityHashCode(ctx);
        //开启一个线程
        Runnable runnable = () -> {
            System.out.println("每10秒执行一次任务");
        };
        if(Objects.isNull(context)){
            System.out.println("无...");
            // 安排一个定时任务
            scheduledFuture = ctx.channel().eventLoop().scheduleAtFixedRate(runnable, 0, 10, TimeUnit.SECONDS);
            context=ctx;
        }
        String key = (String) this.data.get("key");

    }


    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {;
        super.channelWritabilityChanged(ctx);
    }

    /**
     * 如果发生异常 或者是用户主动断开连接 会被触发
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
        stopTask(); //关闭定时任务
        System.out.println("有异常发生么..........");
        //super.exceptionCaught(ctx, cause);
    }


    /**
     *
     * @param ctx 上下文
     * @param evt 事件
     * @throws Exception
     * IdleStateEvent 触发后 , 就会传递给管道 的下一个handler去处理
     * 通过调用(触发)下一个handler 的 userEventTiggered , 在该方法中去处理 IdleStateEvent(读空闲，写空闲，读写空闲)
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if(evt instanceof IdleStateEvent) {
            //将  evt 向下转型 IdleStateEvent
            IdleStateEvent event = (IdleStateEvent) evt;
            String eventType = null;
            switch (event.state()) {
                case READER_IDLE:
                  eventType = "读空闲";
                  break;
                case WRITER_IDLE:
                    eventType = "写空闲";
                    break;
                case ALL_IDLE:
                    eventType = "读写空闲";
                    break;
            }
            System.out.println(ctx.channel().remoteAddress() + "--超时时间--" + eventType);
            System.out.println("服务器做相应处理..");

            //如果发生空闲，我们关闭通道
            ctx.channel().close();
            stopTask();
        }
    }


    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // 断开连接后的处理逻辑
        System.out.println("与客户端断开连接：" + ctx.channel().remoteAddress());
        ctx.close();
    }


    /**
     * 停止定时任务
     */
    public void stopTask() {
        // 如果scheduledFuture不为null且未被取消，则取消任务
        if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
            scheduledFuture.cancel(false);
            scheduledFuture = null; // 将引用置为null，避免内存泄漏
        }
    }

}
